#include <fstream>
#include <iostream>
#include <thread>
#include <atomic>
#include <unistd.h>
#include <dirent.h>
#include <cstdlib>
#include "LiveStreamingNode.h"
#include "whip_client.h"
#include <json/json.h>  // jsoncpp


#define WEBRTC_MAX_FD 3000

std::atomic<bool> running(true);

int get_fd_count() {
    int count = 0;
    DIR *dir = opendir("/proc/self/fd");
    if (dir == nullptr) {
        perror("opendir");
        return -1;
    }
    while (readdir(dir)) {
        count++;
    }
    closedir(dir);
    return count;
}

void fd_monitor_thread() {
    while (running.load()) {
        int fd_count = get_fd_count();
        if (fd_count < 0) {
            std::cerr << "[FD Monitor] Failed to get fd count" << std::endl;
        } else {
            // std::cout << "[FD Monitor] Current fd count: " << fd_count << std::endl;
            if (fd_count > WEBRTC_MAX_FD) {
                std::cerr << "[FD Monitor] FD count exceeded max (" << fd_count << " > " << WEBRTC_MAX_FD << "), exiting..." << std::endl;
                whip_stop_stream("FD count exceeded max");
                std::exit(EXIT_FAILURE);
            }
        }
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}


LiveStreamingNode::LiveStreamingNode(ros::NodeHandle &nh) {
    XmlRpc::XmlRpcValue params;
    if (nh.getParam("", params)) {
        if (params.hasMember("cloud_message_topic")) {
            topic_name_ = static_cast<std::string>(params["cloud_message_topic"]);
            ROS_INFO("Loaded topic: %s", topic_name_.c_str());
        } else {
            ROS_WARN("Missing param: cloud_message_topic");
        }

        if (params.hasMember("update_service")) {
            update_service_name_ = static_cast<std::string>(params["update_service"]);
            ROS_INFO("Loaded service: %s", update_service_name_.c_str());
        } else {
            ROS_WARN("Missing param: update_service");
        }
        _video_source = static_cast<std::string>(params["video_source"]);
        _audio_source = static_cast<std::string>(params["audio_source"]);
        _latency = static_cast<int>(params["latency"]);
        _log_level = static_cast<int>(params["log_level"]);

    } else {
        ROS_WARN("Failed to load XmlRpc parameters from private namespace.");
    }
    message_sub_ = nh.subscribe(topic_name_, 10, &LiveStreamingNode::cloudMessageCallback, this);
    state_update_client_ = nh.serviceClient<pack_msg::StateChangeNotice>(update_service_name_);

    // 初始化默认配置
    default_config_.available_video_number = 1;
    default_config_.coexist_video_number_max = 1;
    {
        DeviceInfo dev;
        dev.sn = "CZI202506230101";
        dev.available_video_number = 1;
        dev.coexist_video_number_max = 1;

        CameraInfo cam;
        cam.camera_index = "700-0-0";
        cam.available_video_number = 1;
        cam.coexist_video_number_max = 1;

        VideoInfo vid;
        vid.video_index = "main";
        vid.video_type = "H264";
        vid.switchable_video_types = {"normal"};

        cam.video_list.push_back(vid);
        dev.camera_list.push_back(cam);
        default_config_.device_list.push_back(dev);
    }

    // loadOrUpdateConfig();
}

bool LiveStreamingNode::loadOrUpdateConfig() {
    bool need_update = false;
    std::ifstream ifs(config_file_path_);

    if (!ifs || ifs.peek() == std::ifstream::traits_type::eof()) {
        need_update = true;
    } else {
        try {
            Json::Value root;
            ifs >> root;
            if (!current_config_.fromJson(root)) {
                ROS_WARN("Failed to parse config, using default.");
                need_update = true;
            } else {
                // 比较current_config_和default_config_，简单比较available_video_number是否相同示例
                if (current_config_.available_video_number != default_config_.available_video_number) {
                    need_update = true;
                }
                // TODO: 更完整的比较可以自定义一个比较函数
            }
        } catch (...) {
            ROS_WARN("Exception parsing config, using default.");
            need_update = true;
        }
    }

    if (need_update) {
        std::ofstream ofs(config_file_path_);
        if (ofs) {
            ofs << default_config_.toJson().toStyledString();
            ROS_INFO("Updated config file with default values.");
            return notifyStateChange(0x01);
        }
        ROS_ERROR("Failed to write config file");
        return false;
    }

    return true;
}

bool LiveStreamingNode::notifyStateChange(int id) {
    pack_msg::StateChangeNotice srv;
    srv.request.notice_update_id = id;
    if (state_update_client_.call(srv)) {
        if (srv.response.result) {
            ROS_INFO("StateChangeNotice success.");
            return true;
        } else {
            ROS_WARN("StateChangeNotice failed on server side.");
        }
    } else {
        ROS_ERROR("Failed to call service StateChangeNotice.");
    }
    return false;
}

void LiveStreamingNode::cloudMessageCallback(const pack_msg::CompositeData::ConstPtr &msg) {
    const std::string &method = msg->method;

    if (method == "live_start_push" || method == "live_stop_push") {
        const pack_msg::LiveSetting &src = msg->live_data;

        ROS_INFO("------ LiveSetting ------");
        ROS_INFO("video_id        : %s", src.video_id.c_str());
        ROS_INFO("url             : %s", src.url.c_str());
        ROS_INFO("url_type        : %d", src.url_type);
        ROS_INFO("video_quality   : %d", src.video_quality);
        ROS_INFO("video_type      : %s", src.video_type.c_str());
        ROS_INFO("camera_position : %d", src.camera_position);
        // 保存到类成员
        live_setting_.video_id = src.video_id;
        live_setting_.url = src.url;
        live_setting_.url_type = src.url_type;
        live_setting_.video_quality = src.video_quality;
        live_setting_.video_type = src.video_type;
        live_setting_.camera_position = src.camera_position;

        if (method == "live_start_push") {
            startLive(live_setting_);
        } else {
            stopLive(live_setting_);
        }
    } else {
        ROS_INFO("Ignored method: %s", method.c_str());
    }
}

void LiveStreamingNode::startLive(const pack_msg::LiveSetting &setting) {
    ROS_INFO("Starting live stream: %s", setting.video_id.c_str());
    // TODO: 实现启动直播逻辑
    whip_set_video(_video_source.c_str());
    whip_set_audio(_audio_source.c_str());
    whip_set_url(setting.url.c_str());
    whip_set_latency(_latency);
    whip_set_loglevel(_log_level);
    int ret = whip_start_stream();
    if(ret < 0)
    {
        whip_stop_stream("start stream failed");
    }

}

void LiveStreamingNode::stopLive(const pack_msg::LiveSetting &setting) {
    ROS_INFO("Stopping live stream: %s", setting.video_id.c_str());
    whip_stop_stream("normal exit");

}

void LiveStreamingNode::run() {
    ros::Rate rate(10);  // 10 Hz
    while (ros::ok()) {
        ros::spinOnce();
        rate.sleep();
    }
}
int main(int argc, char **argv) {
    ros::init(argc, argv, "live_streaming_node");
    whip_client_init();
    std::thread monitor(fd_monitor_thread);
    ros::NodeHandle nh;

    LiveStreamingNode node(nh);
    node.run();
    whip_client_uninit();

    return 0;
}